package top.byfree.jbyan.saber.controller

import cn.dev33.satoken.annotation.SaCheckPermission
import cn.dev33.satoken.stp.StpUtil
import jakarta.validation.Valid
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.io.Resource
import org.springframework.http.ContentDisposition
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.validation.BindException
import org.springframework.validation.FieldError
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import top.byfree.jbyan.saber.bean.dto.FilterUserDto
import top.byfree.jbyan.saber.bean.dto.RegisterDto
import top.byfree.jbyan.saber.bean.dto.UserDto
import top.byfree.jbyan.saber.common.AddGroup
import top.byfree.jbyan.saber.common.R
import top.byfree.jbyan.saber.common.ok
import top.byfree.jbyan.saber.common.result
import top.byfree.jbyan.saber.exception.SaberServiceException
import top.byfree.jbyan.saber.service.UserService

/**
 * 用户控制层
 *
 * @author jbyan
 * @since 21/3/2024
 */
@RestController
@RequestMapping("user")
class UserController(
    @Autowired private val userService: UserService
) {

    /**
     * 获取当前用户的详细信息
     *
     */
    @GetMapping
    fun getCurrent() = ok(data = StpUtil.getSession().get("user"))

    /**
     * 新增用户
     *
     * @param userDto 用户详情
     */
    @PutMapping
    fun add(
        @RequestBody @Validated(AddGroup::class) userDto: UserDto
    ): R<Boolean> {
        // 重复用户名称校验
        userService.byUsername(userDto.username!!)?.let {
            // 存在用户名称
            val be = BindException(userDto, "top.byfree.jbyan.saberblog.bean.dto.RegisterDto")
            be.addError(FieldError("RegisterDto", "username", "用户名已存在"))
            throw be
        }
        return result(userService.add(userDto))
    }

    /**
     * 根据用户id获取用户详细信息
     *
     * 限拥有 sys:user:cat 权限用户调用
     *
     * @param userId 用户Id
     */
    @GetMapping("{userId}")
    @SaCheckPermission("sys:user:cat")
    fun get(@PathVariable userId: String) =
        userService.getOne(userId)?.let { ok(data = it) } ?: throw SaberServiceException("获取用户Id不存在")

    /**
     * 根据用户编号获取用户下角色列表
     *
     * @param userId 用户编号
     */
    @GetMapping("role/{userId}")
    @SaCheckPermission("sys:user:cat")
    fun getRoleList(
        @PathVariable userId: String
    ) = ok(data = userService.getRoleList(userId))

    /**
     * 分页条件获取用户列表
     *
     * 限拥有 sys:user:cat 权限用户调用
     *
     * @param size 每页数据个数
     * @param current 当前业
     */
    @PostMapping("page/{size}/{current}")
    @SaCheckPermission("sys:user:cat")
    fun page(
        @PathVariable size: Int,
        @PathVariable current: Int,
        @RequestBody filterUserDto: FilterUserDto
    ) = ok(data = userService.page(size, current, filterUserDto))

    /**
     * 导出excel文件
     *
     * @param size 每页数据个数
     * @param current 当前页
     */
    @PostMapping("export/{size}/{current}")
    @SaCheckPermission("sys:user:export")
    fun export(
        @PathVariable size: Int,
        @PathVariable current: Int,
        @RequestBody filterUserDto: FilterUserDto
    ): ResponseEntity<ByteArray> {
        val bytes = userService.excel(size, current, filterUserDto)
        val headers = HttpHeaders()
        headers.contentType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
        headers.contentDisposition = ContentDisposition.attachment().filename("user.xlsx").build()
        return ResponseEntity.ok()
            .headers(headers)
            .body(bytes)
    }

    /**
     * 修改当前用户信息
     *
     * @param userDto 用户修改请求实体
     */
    @PostMapping
    fun updateCurrent(@Validated @RequestBody userDto: UserDto) = result(userService.updateCurrent(userDto))

    /**
     * 修改指定用户信息
     *
     * 限拥有 sys:user:update 权限的用户调用
     *
     * @param userDto 用户修改请求实体
     */
    @PostMapping("{userId}")
    @SaCheckPermission("sys:user:update")
    fun update(
        @PathVariable userId: String,
        @Validated @RequestBody userDto: UserDto
    ) = result(userService.update(userId, userDto))

    /**
     * 删除指定用户
     *
     * 限制拥有 sys:user:delete 权限的用户调用
     *
     * @param userId 用户Id
     */
    @DeleteMapping("{userId}")
    @SaCheckPermission("sys:user:delete")
    fun delete(
        @PathVariable userId: String
    ) = result(userService.delete(mutableListOf(userId)))


    /**
     * 修改用户拥有角色
     *
     * @param userId 用户Id
     * @param roles 角色Id列表
     */
    @PostMapping("role/{userId}")
    @SaCheckPermission("sys:user:role")
    fun editRole(
        @PathVariable userId: String,
        @RequestBody roles: MutableList<String>
    ): R<Unit> {
        userService.editRole(userId, roles)
        return ok()
    }

}